package com.common.frame.net

import com.common.frame.bean.HttpResponse
import com.common.frame.bean.MessageEvent
import com.common.frame.bean.ResponseThrowable
import com.hjq.toast.ToastUtils
import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
import retrofit2.HttpException
import java.net.ConnectException
import java.net.UnknownHostException

object NetLaunchManager {

    fun <T> launchRequest(
        block: suspend () -> HttpResponse<T>,
        success: (T) -> Unit = {},
        error: (ResponseThrowable) -> Unit = {}
    ) {
        CoroutineScope(Dispatchers.Main).launch {
            launchRequestSuspend(block, success, error)
        }
    }

    /**
     * @description 依附式网络发送
     *
     * @date: 2021/9/16 17:44
     * @author: zengqingshuai
     * @param
     * @return
     */
    suspend fun <T> launchRequestSuspend(
        block: suspend () -> HttpResponse<T>,
        success: (T) -> Unit = {},
        error: (ResponseThrowable) -> Unit = {},
        response: ((HttpResponse<T>) -> Unit)? = null,
        complete: () -> Unit = {},
        withDelay: Long = 15000
    ) {
        runCatching {
            withContext(Dispatchers.IO) {
                withTimeout(withDelay) {
                    block()
                }
            }
        }.onSuccess {
            response?.invoke(it)
            when (it.code) {
                "1000" -> success.invoke(it.data)
                else -> error(ResponseThrowable("${it.code}", it.message))
            }
            complete()
        }.onFailure {
            if (it is HttpException || it is ConnectException || it is UnknownHostException || it is TimeoutCancellationException) {
//                ToastUtils.show("网络异常")
                error(ResponseThrowable(msg = it.message ?: "", e = it))
            } else {
                error(ResponseThrowable(msg = it.message ?: "", e = it))
            }
            complete()
        }
    }

    suspend fun <T : Any> request(call: suspend () -> HttpResponse<T>): HttpResponse<T> {
        return call.invoke().also {
            when (it.code) {
                "1000" -> {
                }
                else -> throw ResponseThrowable(it.code, it.message)
            }
        }
    }

    fun <T> HttpResponse<T>.response(): HttpResponse<T> {
        return also {
            when (it.code) {
                "1000" -> {
                }
                else -> {
                    throw ResponseThrowable(it.code, it.message)
                }
            }
        }
    }

}